using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Forest.Cat.Domain.Entities;
using Forest.Core;
using Forest.Core.Caching;
using Forest.Core.Data;
using Forest.Core.Events;
using Forest.Cat.Domain.Shared;

namespace Forest.Cat.Domain.Services.Applications
{
    public partial class ApplicationService:IApplicationService
    {
        #region Constants
        private const string APPLICATION_BY_ID_KEY = "application.id-{0}";
        private const string APPLICATION_PATTERN_KEY = "application.";
        #endregion

        #region Fields
        private readonly IRepository<Application> _applicationRepository;
		private readonly ICacheManager _cacheManager;
        private readonly IEventPublisher _eventPublisher;
        private readonly IGenerateNumberService _generateNumberService;
        #endregion

        #region Ctor
        public ApplicationService(IRepository<Application> applicationRepository, ICacheManager cacheManager,
            IEventPublisher eventPublisher, IGenerateNumberService generateNumberService)
        {
            _applicationRepository = applicationRepository;
			_cacheManager = cacheManager;
            _eventPublisher = eventPublisher;
            _generateNumberService = generateNumberService;
        }
        #endregion

        #region Base Methods
        public virtual void DeleteApplication(Application application)
        {
            if (application == null)
                throw new ArgumentNullException("Application");

            _applicationRepository.Delete(application);
			_cacheManager.RemoveByPattern(APPLICATION_PATTERN_KEY);
			_eventPublisher.EntityDeleted(application);
        }

        public Application GetApplicationById(Guid applicationId)
        {
            if (applicationId == Guid.Empty)
                return null;
            string key = string.Format(APPLICATION_BY_ID_KEY, applicationId);

            return _cacheManager.Get(key, () => {
                var cl = _applicationRepository.GetById(applicationId);
                return cl;
            });
        }

        public virtual IPagedList<Application> GetAllApplications(int pageIndex, int pageSize)
        {
            var query = _applicationRepository.Table;
            query = query.OrderBy(w => w.Id);
            var items = new PagedList<Application>(query, pageIndex, pageSize);
            return items;
        }

        public virtual void InsertApplication(Application application)
        {
            if (application == null)
                throw new ArgumentNullException("Application");
            _applicationRepository.Insert(application);
			_cacheManager.RemoveByPattern(APPLICATION_PATTERN_KEY);
			_eventPublisher.EntityInserted(application);
        }

        public virtual void UpdateApplication(Application application)
        {
            if (application == null)
                throw new ArgumentNullException("Application");
            _applicationRepository.Update(application);
			_cacheManager.RemoveByPattern(APPLICATION_PATTERN_KEY);
			_eventPublisher.EntityUpdated(application);
        }
        #endregion

        #region Extend Methods
        /// <summary>
        /// Search PageList by JobseekerId
        /// </summary>
        /// <param name="jobseekerId"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public IPagedList<Application> GetApplicationsByJobseekerId(Guid jobseekerId, int pageIndex, int pageSize)
        {
            var query = _applicationRepository.Table.Where(item => item.JobseekerId == jobseekerId).OrderByDescending(o =>
                o.DateApplied);
            var items = new PagedList<Application>(query, pageIndex, pageSize);
            return items;
        }

        public IQueryable<Application> GetApplicationsByJobseekerId(Guid jobseekerId)
        {
            return _applicationRepository.Table.Where(item => item.JobseekerId == jobseekerId);
        }
        #endregion

        public Guid CreateId
        {
            get
            {
                return _generateNumberService.GenerateId<Application>(_applicationRepository, GenerateType.Application);
            }
        }
    }
}
